package com.xunk.equipment.service.mandun.util;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.xunk.common.core.utils.HttpUtil;
import com.xunk.common.core.utils.StringUtils;
import com.xunk.common.core.utils.serialization.JsonSerializer;
import com.xunk.equipment.config.MandunConfig;
import com.xunk.equipment.service.mandun.constant.MandunConstant;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletRequestWrapper;
import java.io.BufferedReader;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;

/**
 * @ProjectName: xunk
 * @Package: com.xunk.equipment.service.ruying.mandun.util
 * @ClassName: MandunUtil
 * @Author: luanzhiwei
 * @Description: 曼顿使用工具类
 * @Date: 2021/3/27 14:49
 * @Version: 1.0
 */
public class MandunUtil {


    private static Logger LOGGER = LoggerFactory.getLogger(MandunUtil.class);


    private static final char[] hc = "0123456789abcdef".toCharArray();

    /**
     * 根据输入字符串，计算MD5码
     *
     * @param param
     * @return
     */
    public static String MD5(String param) {
        MessageDigest md;
        try {
            md = MessageDigest.getInstance("MD5");
            md.reset();
            md.update(param.getBytes(StandardCharsets.UTF_8));
            byte[] d = md.digest();
            StringBuilder r = new StringBuilder(d.length * 2);
            for (byte b : d) {
                r.append(hc[(b >> 4) & 0xF]);
                r.append(hc[(b & 0xF)]);
            }
            return r.toString();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }


    /**
     * 对请求参数中的入参进行排序并签名
     *
     * @param request
     * @param appSecret
     * @return
     */
    public static String sign(TreeMap request, String appSecret) {
        // 拼接参数
        StringBuffer key = new StringBuffer();
        StringBuffer value = new StringBuffer();
        Iterator<Map.Entry<String, Object>> iterator = request.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, Object> next = iterator.next();
            key.append(next.getKey());
            value.append(next.getValue());
        }
        // 验证
        String sign = MD5(value.toString() + appSecret);
        return sign;
    }

    /**
     * 获取公共参数，client_id也就是曼顿提供的appKey
     *
     * @param method
     * @param clientId
     * @param token
     * @return
     */
    public static TreeMap getCommonRequest(String method, String clientId, String token) {
        TreeMap<String, Object> request = new TreeMap<>();
        request.put("client_id", clientId);
        request.put("access_token", token);
        request.put("timestamp", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")));
        request.put("method", method);
        return request;
    }

    /**
     * 获取临时code
     *
     * @return
     */
    public static String getCode(MandunConfig config) {
        LOGGER.info("【获取code】");

        Map<String, Object> bodyParam = new HashMap<>();
        //公共参数
        bodyParam.put(MandunConstant.RESPONSE_TYPE, MandunConstant.CODE);
        bodyParam.put(MandunConstant.CLIENT_ID, config.getAppKey());
        bodyParam.put(MandunConstant.REDIRECT_URI, config.getRedirectUrl());
        bodyParam.put(MandunConstant.UNAME, config.getUname());
        bodyParam.put(MandunConstant.PASSWD, config.getPasswd());
        //请求头信息
        Map<String, String> headParam = new HashMap<>();
        headParam.put(MandunConstant.CONTENT_TYPE, MandunConstant.CONTENT_TYPE_JSON);
        JSONObject jsonObject = HttpUtil.doPoststr(config.getUrlPrefix() + config.getCodeUrlSuffix(), JSON.toJSONString(bodyParam), headParam);
        LOGGER.info("【获取code】返回信息：{}", jsonObject.toJSONString());
        return jsonObject.getString("code");
    }

    /**
     * 获取token
     *
     * @return
     */
    @SuppressWarnings("rawtypes")
    public static JSONObject getToken(MandunConfig config) {
        LOGGER.info("【获取token】");
        String code = getCode(config);
        Map<String, Object> bodyParam = new HashMap<>();
        //公共参数
        bodyParam.put(MandunConstant.CLIENT_ID, config.getAppKey());
        bodyParam.put(MandunConstant.CLIENT_SECRET, MD5(config.getAppKey() + MandunConstant.AUTHORIZATION_CODE + config.getRedirectUrl() + code + config.getAppSecret()));
        bodyParam.put(MandunConstant.GRANT_TYPE, MandunConstant.AUTHORIZATION_CODE);
        bodyParam.put(MandunConstant.REDIRECT_URI, config.getRedirectUrl());
        bodyParam.put(MandunConstant.CODE, code);

        //请求头信息
        Map<String, String> headParam = new HashMap<>();
        headParam.put(MandunConstant.CONTENT_TYPE, MandunConstant.CONTENT_TYPE_JSON);
        JSONObject jsonObject = HttpUtil.doPoststr(config.getUrlPrefix() + config.getTokenUrlSuffix(), JSON.toJSONString(bodyParam), headParam);
        LOGGER.info("【获取token】返回信息：{}", jsonObject.toJSONString());
        return jsonObject;
    }

    /**
     * 刷新token，使用refreshToken刷新后，access_token和refresh_token都会变化。需要重新存入redis
     *
     * @param refreshToken
     */
    public static JSONObject refreshToken(MandunConfig config, String refreshToken) {
        LOGGER.info("【刷新token】");
        Map<String, Object> bodyParam = new HashMap<>();
        //公共参数
        bodyParam.put(MandunConstant.CLIENT_ID, config.getAppKey());
        bodyParam.put(MandunConstant.CLIENT_SECRET, MD5(config.getAppKey() + MandunConstant.GRANT_TYPE_REFRESH_TOKEN + config.getRedirectUrl() + refreshToken + config.getAppSecret()));
        bodyParam.put(MandunConstant.GRANT_TYPE, MandunConstant.GRANT_TYPE_REFRESH_TOKEN);
        bodyParam.put(MandunConstant.REDIRECT_URI, config.getRedirectUrl());
        bodyParam.put(MandunConstant.GRANT_TYPE_REFRESH_TOKEN, refreshToken);

        Map<String, String> headParam = new HashMap<>();
        headParam.put(MandunConstant.CONTENT_TYPE, MandunConstant.CONTENT_TYPE_JSON);
        JSONObject jsonObject = HttpUtil.doPoststr(config.getUrlPrefix() + config.getRefreshTokenUrlSuffix(), JsonSerializer.serialize(bodyParam), headParam);

        LOGGER.info("【刷新token】返回：{}", jsonObject.toJSONString());
        return jsonObject;
    }

    /**
     * 判断曼顿返回是否成功，返回状态码（0表示是成功，1表示是失败，2表示accessToken过期）
     *
     * @param jsonObject
     * @return
     */
    public static boolean isSuccess(JSONObject jsonObject) {
        if (StringUtils.equals(jsonObject.getString(MandunConstant.CODE), "0")) {
            return true;
        }
        return false;
    }

    /**
     * 是否过期，2过期
     *
     * @param jsonObject
     * @return
     */
    public static boolean isExpire(JSONObject jsonObject) {
        if (StringUtils.equals(jsonObject.getString(MandunConstant.CODE), "2")) {
            return true;
        }
        return false;
    }

    /**
     * 获取曼顿返回值的message
     *
     * @param jsonObject
     * @return
     */
    public static String getMsg(JSONObject jsonObject) {
        return jsonObject.getString(MandunConstant.MESSAGE);
    }


    /**
     * 获取 HttpServletRequest 中 Body 参数
     *
     * @param request
     * @return
     */
    public static String getBodyString(HttpServletRequestWrapper request) {
        BufferedReader br = null;
        StringBuilder sb = new StringBuilder();
        try {
            br = request.getReader();
            String str;
            while ((str = br.readLine()) != null) {
                sb.append(str);
            }
            br.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (null != br) {
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return sb.toString();
    }

}
